#pragma once
#include <iostream>
#include "myLog.hpp"
#include "mySock.hpp"
#include "Err.hpp"
#include <memory>
#include <pthread.h>
#include <functional>
#include<sstream>
#include<vector>
#include <sys/types.h>
#include <sys/stat.h> 
#include <unistd.h>
using namespace std;
using func_t = function<string(string &)>;
class httpserver;

class ThreadData
{
public:
    ThreadData(const int &sock, const string &ip, const uint16_t &port, httpserver *tsvr)
        : sock_(sock), ip_(ip), port_(port), tsvr_(tsvr)
    {
    }

    ~ThreadData()
    {
    }

public:
    int sock_;
    string ip_;
    uint16_t port_;
    httpserver *tsvr_;
};

static const uint16_t default_port = 8080;
class httpserver
{
public:
    httpserver() {}
    httpserver(func_t f, uint16_t port = default_port)
        : func_(f), port_(port)
    {
    }
    ~httpserver() {}
    void Init()
    {
        listenSock_.Socket();
        listenSock_.Bind(port_);
        listenSock_.Listen();
        logMessge(INFO, "准备就绪！");
    }
    void httpServer(int sock, const string &ip, const uint16_t &port)
    {
        char buf[4096];
        string message ;

        ssize_t s = recv(sock, buf, sizeof(buf) - 1, 0);
        if (s > 0)
        {
            logMessge(DEBUG, "收到请求！");
            buf[s] = 0;
            message = buf;
            string resp = func_(message);
            send(sock, resp.c_str(), resp.size(), 0);
            logMessge(DEBUG, "发送成功！");
        }
        else
        {
            logMessge(INFO, "客户端退出！");
        }
    }
    static void *pthreadRoutine(void *args)
    {

        pthread_detach(pthread_self());

        ThreadData *td = static_cast<ThreadData *>(args);
        td->tsvr_->httpServer(td->sock_, td->ip_, td->port_);
        close(td->sock_);

        delete td;
        return nullptr;

    }
    void Start()
    {
        while (1)
        {
            string cilentIp;
            uint16_t cilentPort;
            int sock = listenSock_.Accept(&cilentIp, &cilentPort);
            if (sock < 0)
                continue;
            pthread_t tid;
            ThreadData *td = new ThreadData(sock, cilentIp, cilentPort, this);
            pthread_create(&tid, nullptr, pthreadRoutine, td);
        }
    }

private:
    uint16_t port_;
    Sock listenSock_;
    func_t func_;
};